<template>
  <div class="project-detail detail_page_layer">
    <div class="header">
      <div class="header-content-box">
        <div class="header-left">
          <div class="title">{{curProject.projectName}}</div>
          <div class="desc">{{curProject.profile}}</div>
        </div>
        <div class="header-right">
          <div class="action-box">
            <div class="action">
              <span @click="editProject" :class="{'not-allowed': curProject.type}"><i class="icon-cfg"></i>编辑参数</span>
              <span @click="openProject" :class="{'not-allowed': curProject.type}"><div class="icon-open"></div>公开该项目</span>
            </div>
          </div>
          <div class="project-env">
            <span v-if="curProject.algorithm"><img src="@/common/image/icon-project/icon-project-algorithm-light.png">{{curProject.algorithm}}</span>
            <span v-if="curProject.language"><img src="@/common/image/icon-project/icon-project-language-light.png">{{curProject.language}}</span>
          </div>
        </div>
      </div>
      <ul class="nav-list">
        <li class="main-nav-list nav-left clearfix">
          <ul class="main-nav-list-container">
            <li class="nav-item link-item" :class="{'active': activeTab === 0}" @click="toggleActive(0)">
              <i class="icon icon-task"></i>
              运行任务
              </li>
            <li class="nav-item link-item" :class="{'active': activeTab === 1}" @click="toggleActive(1)">
              <i class="icon icon-code"></i>
              项目代码
              </li>
            <li class="nav-item link-item" :class="{'active': activeTab === 2}" @click="toggleActive(2)">
              <i class="icon icon-data-set"></i>
              数据集
              </li>
            <li class="nav-item link-item" :class="{'active': activeTab === 3}" @click="toggleActive(3)">
              <i class="icon icon-notes"></i>
              笔记
              </li>
          </ul>
        </li>
        <li class="main-nav-list nav-right">
          <div class="header-button">
            <el-button size="medium" class="iconboxs" v-if="debuggerState === 0" @click="clickDebugger"><i class="icon-debugger"></i>调试</el-button>
            <el-button size="medium" class="button-blue" v-else-if="debuggerState === 1" :loading="true">等待中...</el-button>
            <el-button size="medium" class="iconboxs button-blue" v-else @click="toJupyter"><i class="icon-debuggerfff"></i>启动Jupyter</el-button>
            <el-button size="medium" type="primary" @click="createTask"><span class="new-task-text"><i class="el-icon-plus el-icon--left"></i>新建任务</span></el-button>
          </div>
        </li>
      </ul>
    </div>
    <div class="content">
      <router-view ref="task-view" v-if="isRouterAlive" @update-taskno="updateLatestTaskNo" :curProject="curProject"></router-view>
    </div>
    <!-- 新建任务 -->
    <el-dialog
      title="新建任务"
      :visible.sync="dialog.createTask"
      :pos="'center'"
      :width="'800px'">
      <div class="task-list-main-container">
        <el-form label-position="top" class="form" :model="taskForm" :rules="rulesForm" ref="taskForm" @submit.native.prevent>
          <div class="form-task-container">
            <div class="form-task-left">
              <ul class="task-list">
                <li v-for="(item, i) in taskList" :key="i" class="task-item" :class="{'active': curTaskArrId === i}" @click="chooseTask(i)">
                  <span :class="{'nochecked': item.noChecked === true}">{{item.name}}</span>
                  <i class="task-del" @click.stop.prevent="delTask(i)">X</i>
                </li>
              </ul>
              <div class="task-add">
                <div class="task-add-btn" @click="addTask">+ 添加任务</div>
              </div>
            </div>
            <div class="form-task-right">
              <div class="task-right-box">
                <div class="task-right-item">
                  <div>
                    <el-form-item prop="name">
                      <div class="title required">name：</div>
                      <el-input class="input" v-model="taskForm.name" autocomplete="off" @change="taskInputChange('name', false, true)"></el-input>
                    </el-form-item>
                  </div>
                  <div>
                    <el-form-item>
                      <div class="title">minSucceededTaskCount：</div>
                      <el-input class="input" v-model="taskForm.minSucceededTaskCount" autocomplete="off" @change="taskInputChange('minSucceededTaskCount', true, true, 1)" placeholder="null或不小于1的数值"></el-input>
                    </el-form-item>
                  </div>
                  <div>
                    <el-form-item prop="cpuNumber">
                      <div class="title required">cpu number：</div>
                      <el-input class="input" v-model="taskForm.cpuNumber" autocomplete="off" @change="taskInputChange('cpuNumber', true, true, 1)"  placeholder="大于0的数值"></el-input>
                    </el-form-item>
                  </div>
                  <div>
                    <el-form-item prop="memoryMB">
                      <div class="title required">memory：</div>
                      <el-input class="input" v-model="taskForm.memoryMB" autocomplete="off" @change="taskInputChange('memoryMB', true, true, 100)"  placeholder="不小于100的数值">
                        <template slot="append">MB</template>
                      </el-input>
                    </el-form-item>
                  </div>
                </div>
                <div class="task-right-item">
                  <div>
                    <el-form-item prop="taskNumber">
                      <div class="title required">task number：</div>
                      <el-input class="input" v-model="taskForm.taskNumber" autocomplete="off" @change="taskInputChange('taskNumber', true, true, 1)" placeholder="大于0的数值"></el-input>
                    </el-form-item>
                  </div>
                  <div>
                    <el-form-item>
                      <div class="title">minFailedTaskCount：</div>
                      <el-input :controls="false" class="input" v-model="taskForm.minFailedTaskCount" autocomplete="off" @change="taskInputChange('minFailedTaskCount', true, true, 1)" placeholder="null或不小于1的数值"></el-input>
                    </el-form-item>
                  </div>
                  <div>
                    <el-form-item>
                      <div class="title">gpu number：</div>
                      <el-input class="input" v-model="taskForm.gpuNumber" autocomplete="off" @change="taskInputChange('gpuNumber', true, true, 0)"  placeholder="不小于0的数值"></el-input>
                    </el-form-item>
                  </div>
                  <div>
                    <el-form-item prop="shmMB">
                      <div class="title">Shared memory：</div>
                      <el-input class="input" v-model="taskForm.shmMB" autocomplete="off" @change="taskInputChange('shmMB', true, true)"  placeholder="不大于Shared memory的数值">
                        <template slot="append">MB</template>
                      </el-input>
                    </el-form-item>
                  </div>
                </div>
              </div>
              <div class="task-right-item-bottom">
                <el-form-item prop="command">
                  <div class="title required">command：</div>
                  <el-input class="input" type="textarea" :rows="3" v-model="taskForm.command" autocomplete="off" @change="taskInputChange('command', false, true)"  placeholder="Executable command for tasks in the task role, can not be empty.Value must match the pattern \S+."></el-input>
                </el-form-item>
              </div>
            </div>
          </div>
        </el-form>
        <div slot="footer" class="dialog-footer basebtn">
          <div>
            <button type="primary" @click="submitTask()" class="dialog-button lan">运 行</button>
            <button @click="resetForm" class="dialog-button active last">重 置</button>
          </div>
        </div>
      </div>
    </el-dialog>
    <!-- 公开项目弹窗显示 -->
    <el-dialog
      title=""
      :visible.sync="openProjectState"
      :pos="'center'"
      :width="'386px'"
      class="open-project-no">
      <div class="no-wrapper">
        <h4 class="title">公开项目之前，请先公开以下依赖的数据</h4>
        <div class="dataset" v-if="openproDatalist.length > 0">
          <h5 class="tit">数据集</h5>
          <ul class="items">
            <li class="item" v-for="(item, index) in openproDatalist" :key="index" @click="linkDateset(item)">
              {{item.name}}
            </li>
          </ul>
        </div>
        <div class="model">
          <h5 class="tit">模型</h5>
          <ul class="items">
            <li class="item" v-for="(item, index) in openproModelList" :key="index" @click="linkModel(item)">
              {{item.modelName}}
            </li>
          </ul>
        </div>
      </div>
    </el-dialog>
    <!-- 调试任务 -->
    <el-dialog
      title=""
      :visible.sync="dialog.debugger"
      :pos="'center'"
      :width="'550px'"
      :show-close="false"
      @open="openDebuggerDialog"
      class="debugger-dialog">
      <div class="debugger-content">
        <span class="title">GPU类型</span>
        <el-select class="debugger-gpu-select" v-model="debuggerGPUType" placeholder="请选择">
          <el-option
            v-for="item in gpuTypeOptions"
            :key="item.value"
            :label="item.value"
            :value="item.value">
          </el-option>
        </el-select>
        <span class="title">GPU个数</span>
        <el-input-number class="debugger-gpu-number"  v-model="debuggerGPUNumber" controls-position="right"  @change="handledebuggerGPUNumberChange" :min="1" :max="8"></el-input-number>
        <div class="cost-payby" v-if="payByList.length > 0">
          <h4 class="title">支付方式</h4>
          <el-radio-group class="payby-group" v-model="payBy">
            <el-radio class="payby-group-item" v-for="(item, index) in payByList" :key="index" :label="item.teamId" @change="selectPowerBy($event, item)">以{{item.teamName}}账号支付<span v-if="selectedTeamId == item.teamId" class="payby-group-item-remaining">剩余&nbsp;{{Number(item.power).toFixed(1)}}&nbsp;算力</span></el-radio>
          </el-radio-group>
        </div>
        <p class="debugger-text debugger-text-first">当前配置：{{ debugConfig }}</p>
        <p class="debugger-text">按当前配置，任务运行需要耗费<span class="debugger-text-cal">{{debugCalPower}} 算力/小时</span></p>
        <p class="debugger-tips">提示：调试任务需要手动停止，请务必在任务结束后，在任务列表手动停止该任务，以免造成不必要的算力损失。</p>
      </div>
      <div slot="footer" class="dialog-footer">
        <div>
          <button @click="dialog.debugger=false" class="debugger-footer-btn">取 消</button>
          <button type="primary" class="debugger-footer-btn debugger-footer-active" @click="createDebuggerTask">确 定</button>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { createTask, getJobJupyterUrl, getProjectDetailByProjectId, getIdFindDataset, getLastJupyterJobConfig } from '@/api/project'
import { getTeamListWithPower } from '@/api/team'
import { getCalculationPowerConfList, getUserCalculationPower, addTeamTaskRelation } from '@/api/order'
import { randomNumber, isNewId } from '@/common/js/getRandCharacter'
import { imagesGetList } from '@/api/image'
import { mapMutations, mapGetters } from 'vuex'
import { throttle } from '@/common/js/utils'
import qs from 'qs'
export default {
  data () {
    // 表单校验-SharedMemory
    var validateSharedMemory = (rule, value, callback) => {
      if (Number(this.taskForm.shmMB) > Number(this.taskForm.memoryMB)) {
        callback(new Error('Shared memory值必须小于memory'))
      } else {
        callback()
      }
    }
    return {
      gpuTypeOptions: [],
      debuggerGPUType: 'debug',
      debuggerGPUNumber: 1,
      curProject: {},
      viewConf: false,
      isRouterAlive: true,
      dialog: {
        createTask: false,
        debuggerTask: false,
        debugger: false
      },
      // Tabs切换路由对照，数组顺序不可变化
      tabsRoutePath: [
        '/project/detail/task',
        '/project/detail/code',
        '/project/detail/dataset',
        '/project/detail/notebook'
      ],
      taskForm: {
        name: 'Task1',
        minSucceededTaskCount: '',
        minFailedTaskCount: '',
        cpuNumber: '',
        taskNumber: '',
        memoryMB: '',
        gpuNumber: '',
        shmMB: '',
        command: ''
      },
      // 表单校验规则
      rulesForm: {
        name: [
          { required: true, message: '请输入任务名称', trigger: 'blur' }
        ],
        cpuNumber: [
          { required: true, message: '请输入cpu number', trigger: 'blur' }
        ],
        memoryMB: [
          { required: true, message: '请输入memory', trigger: 'blur' }
        ],
        taskNumber: [
          { required: true, message: '请输入task number', trigger: 'blur' }
        ],
        shmMB: [
          { validator: validateSharedMemory, trigger: 'blur' }
        ]
      },
      // 当前选择任务
      curTaskArrId: 0,
      // 当前选择查看任务
      curViewTaskArrId: 0,
      // Task数据
      taskList: [
        {
          name: 'Task1',
          minSucceededTaskCount: '',
          minFailedTaskCount: '',
          cpuNumber: '',
          taskNumber: '',
          memoryMB: '',
          gpuNumber: '',
          shmMB: '',
          command: ''
        }
      ],
      jobName: '',
      // 任务信息
      viewTaskList: [{
        name: '',
        command: '',
        cpuNumber: '',
        gpuNumber: '',
        memoryMB: '',
        minFailedTaskCount: '',
        minSucceededTaskCount: '',
        shmMB: '',
        taskNumber: ''
      }],
      // 任务调试状态： 0-初始状态、1-等待中、2-jupyter可用状态
      debuggerState: 0,
      jupyterConfig: {
        'apiVersion': '2.0',
        'kind': 'debug',
        'jobName': '',
        'retryCount': 0,
        'code': {
          projectId: '',
          mountPath: '/code',
          timeStamp: '',
          version: ''
        },
        'model': {
          modelId: '',
          mountPath: '',
          token: ''
        },
        'output': {
          'jobId': ''
        },
        'taskRoles': [
          {
            'taskName': 'task1',
            'memoryMB': 1024,
            'shmMB': 64,
            'taskNumber': 1,
            'cpuNumber': 1,
            'gpuNumber': 1,
            'minFailedTaskCount': null,
            'minSucceededTaskCount': null,
            'command': '',
            'image': '',
            'gpuType': ''
          }
        ]
      },
      // 任务最新代号
      newestTaskNo: 0,
      // jupyter调试链接
      jupyterUrl: '',
      // 定时器
      timer: '',
      // 调试任务当前配置
      debugConfig: '',
      // 调试任务当前配置消耗算力
      debugCalPower: 0,
      // 调试任务当前gpu类型
      curDeubGpuType: '',
      // 公开任务弹窗显示
      openProjectState: false,
      // 私有数据集
      openproDatalist: [],
      // 私有模型
      openproModelList: [],
      // 支付方式
      payBy: -99,
      // 选择支付列表
      payByList: [],
      // 剩余算力
      residualCalculation: 0,
      // 当前用户剩余算力
      surplusCalculationPower: 0,
      createJobLoad: '',
      selectedTeamId: ''
    }
  },
  methods: {
    // 调试任务选择gpu个数
    handledebuggerGPUNumberChange (val) {
      this.debugCalPower = (this.gpuTypeOptions[0].cal_power * val).toFixed(2)
      this.debugConfig = `${this.debuggerGPUNumber}个${this.gpuTypeOptions[0].gpu_type}、${this.debuggerGPUNumber * this.gpuTypeOptions[0].cpu_num}核CPU、${this.debuggerGPUNumber * this.gpuTypeOptions[0].memory_num}G内存、${this.debuggerGPUNumber * this.gpuTypeOptions[0].shared_memory_num}M共享缓存`
    },
    // 打开调试任务弹窗
    openDebuggerDialog () {
      this._getCalculationPowerConfList()
      this._getLastJupyterJobConfig()
    },
    // 最新任务代号-子组件传值
    updateLatestTaskNo (val) {
      this.newestTaskNo = Number(val) + 1
    },
    // tab页切换
    toggleActive (val) {
      let path = this.tabsRoutePath[val]
      this.$router.push({ 'path': path, query: { projectid: this.$route.query.projectid } })
    },
    // 跳转到数据集
    linkDateset (item) {
      item.activeTab = 2
      this.storeDataSet(item)
      this.$router.push(`/dataset/detail`)
    },
    // 跳转到模型
    linkModel (item) {
      this.$router.push({
        path: '/modellump/privatedetailed',
        query: {
          active: 1,
          modelId: item.id,
          modelName: item.modelName
        }
      })
    },
    reloadChildComponent () {
      this.isRouterAlive = false
      this.$nextTick(() => {
        this.isRouterAlive = true
      })
    },
    // toggle 查看任务配置
    toggleViewConf (val) {
      let configObj = JSON.parse(this.curProject.config)
      this.viewTaskList = configObj.taskRoles
      this.viewConf = val
    },
    // 新建任务
    createTask () {
      this.$router.push({ path: '/project/run' })
      return false
    },
    // Tasklist 非空校验
    checkEmptyTaskList () {
      let checkFlag = false
      this.taskList.map((item, index) => {
        if (item.name === '' || item.taskNumber === '' || item.cpuNumber === '' || item.memoryMB === '' || item.command === '') {
          // 数组更新赋值，解决vue数组直接赋值页面不能及时更新状态问题
          let tempItem = this.taskList[index]
          tempItem.noChecked = true
          this.$set(this.taskList, index, tempItem)
          checkFlag = true
        } else {
          let tempItem = this.taskList[index]
          tempItem.noChecked = false
          this.$set(this.taskList, index, tempItem)
        }
      })
      return checkFlag
    },
    // 提交新建任务
    submitTask () {
      this.$refs.taskForm.validate((valid) => {
        if (valid) {
          // 校验taskList列表
          if (this.checkEmptyTaskList()) {
            return false
          }
          this._createTask()
        } else {
          return false
        }
      })
    },
    // 重置表单
    resetForm () {
      this.$refs.taskForm.resetFields()
      this.taskList = [
        {
          name: 'Task1',
          minSucceededTaskCount: '',
          minFailedTaskCount: '',
          cpuNumber: '',
          taskNumber: '',
          memoryMB: '',
          gpuNumber: '',
          shmMB: '',
          command: ''
        }
      ]
    },
    // 选择任务
    chooseTask (index) {
      this.curTaskArrId = index
      this.taskForm.name = this.taskList[index].name
      this.taskForm.minSucceededTaskCount = this.taskList[index].minSucceededTaskCount
      this.taskForm.minFailedTaskCount = this.taskList[index].minFailedTaskCount
      this.taskForm.cpuNumber = this.taskList[index].cpuNumber
      this.taskForm.memoryMB = this.taskList[index].memoryMB
      this.taskForm.taskNumber = this.taskList[index].taskNumber
      this.taskForm.gpuNumber = this.taskList[index].gpuNumber
      this.taskForm.shmMB = this.taskList[index].shmMB
      this.taskForm.command = this.taskList[index].command
    },
    // 选择查看任务
    chooseViewTask (index) {
      this.curViewTaskArrId = index
    },
    // 添加任务
    addTask () {
      let newTaskItem = {
        name: `Task${this.taskList.length + 1}`,
        minSucceededTaskCount: '',
        minFailedTaskCount: '',
        cpuNumber: '',
        memoryMB: '',
        taskNumber: '',
        gpuNumber: '',
        shmMB: '',
        command: ''
      }
      this.taskList.push(newTaskItem)
      this.curTaskArrId = this.taskList.length - 1
      this.chooseTask(this.curTaskArrId)
    },
    // 移除任务
    delTask (i) {
      if (this.taskList.length > 1) {
        this.taskList.splice(i, 1)
      } else {
        return false
      }
    },
    clickDebugger () {
      this.dialog.debugger = true
    },
    // 启动jupyter
    toJupyter () {
      // const { href } = this.$router.resolve({
      //   name: 'jupyterlab',
      //   path: '/jupyter',
      //   query: { projectid: this.curProject.id, path: this.jupyterUrl }
      // })
      const href = this.jupyterUrl.indexOf('https') === -1 ? 'https://' + this.jupyterUrl : this.jupyterUrl
      window.open(href, '_blank')
    },
    /*
      Task输入框输入变化
      valName: 输入值
      isNumberInput：是否数字输入框
      required：是否必填，用于根据输入值变化更新tasklist的状态
      min: 最小值
      max: 最大值
    */
    taskInputChange (valName, isNumberInput, required, min, max) {
      // 判断是否为数字类型输入框，是的话替换非数字输入
      if (this.taskForm[valName] !== '' && isNumberInput) {
        this.taskForm[valName] = this.taskForm[valName].replace(/\D/g, '')
        let num = Number(this.taskForm[valName])
        num = min !== undefined && num < min ? min : num
        num = max !== undefined && num > max ? max : num
        this.taskForm[valName] = num
      }
      // 同步输入表单输入到任务数组
      this.taskList[this.curTaskArrId][valName] = this.taskForm[valName]
      if (required) {
        this.checkEmptyTaskList()
      }
    },
    // 设置任务随机名
    setRandomJobName () {
      let sname = this.curProject.projectName
      let rdString = isNewId(randomNumber())
      let sResult = ''
      if (sname != null && sname.trim().length > 0) {
        if (sname.lastIndexOf('-') === -1) {
          sResult = sname.concat('-' + rdString)
        } else {
          let lastNumber = sname.slice(-1) // 获取最后一位
          let check = isNewId(sname.slice(-6, -1)).slice(-1)
          if (check !== lastNumber) {
            if (lastNumber === '-') {
              sResult = sname.concat(rdString)
            } else {
              sResult = sname.concat('-' + rdString)
            }
          } else {
            let sJudge = sname.substr(0, (sname.lastIndexOf('-')))
            sResult = sJudge.concat('-' + rdString)
          }
        }
      }
      this.jobName = sResult
    },
    // 公开该项目
    openProject () {
      this._getIdFindDataset()
      // this.$router.push({ 'path': '/project/open' })
    },
    // 编辑该项目
    editProject () {
      if (!this.curProject.type) {
        this.$router.push({ 'path': '/project/edit' })
      } else {
        return false
      }
    },
    // 点击启动调试任务
    createDebuggerTask () {
      this.dialog.debugger = false
      throttle(this._createDebuggerTask, 2000)()
    },
    selectPowerBy (label, item) {
      this.residualCalculation = item.power
      this.selectedTeamId = item.teamId
      if (this.residualCalculation) this.residualCalculation = Number(this.residualCalculation).toFixed(1)
      if (!this.residualCalculation) this.residualCalculation = 0
    },
    // 轮询Jupyter查询
    _ajaxLoop (sec = 10000) {
      return setInterval(() => {
        this._getJobJupyterUrl()
      }, sec)
    },
    // 调试任务
    // debuggerTask () {
    //   this.$confirm('').then(() => {

    //   })
    // },
    /*
      -----接口调用-----
    */
    // 查询用户项目详情
    _getProjectDetailByProjectId () {
      let query = `?projectId=${this.$route.query.projectid}`
      getProjectDetailByProjectId(query).then(res => {
        if (res.message.code === 0) {
          this.curProject = res.data
          this.storeProject(res.data)
          this._imagesGetList(res.data.language, res.data.algorithm)
        } else {
          this.$message({ message: res.message.message, showClose: true, type: 'error' })
        }
      })
    },
    // 获取镜像列表 --> 赋值推荐镜像第一个
    _imagesGetList (language, algorithm) {
      const query = `?language=${language}&framework=${algorithm}`
      imagesGetList(query).then(res => {
        if (res.message.code === 0 && res.data && res.data[0]) {
          this.jupyterConfig.taskRoles[0].image = res.data[0].path
        }
      })
    },
    // 判断公开项目
    _getIdFindDataset () {
      const query = `?userId=${this.userInfo.userId}&id=${this.$route.query.projectid}`
      getIdFindDataset(query).then(res => {
        if (res.message.code === 50006 || res.message.code === 50007 || res.message.code === 50008) {
          if (res.data && res.data.dataSets) this.openproDatalist = res.data.dataSets
          if (res.data && res.data.models) this.openproModelList = res.data.models
          this.openProjectState = true
          // this.$message({ message: '该项目使用了私有数据集，暂无法公开!', showClose: true, type: 'error' })
        } else {
          this.$router.push({ 'path': '/project/open' })
        }
      })
    },
    // 创建任务
    _createTask () {
      this.setRandomJobName()
      let configObj = JSON.parse(this.curProject.config)
      configObj.taskRoles = this.taskList.map(item => {
        item.gpuNumber = item.gpuNumber === '' ? 0 : item.gpuNumber
        item.shmMB = item.shmMB === '' ? 64 : item.shmMB
        item.minFailedTaskCount = item.minFailedTaskCount === '' ? null : item.minFailedTaskCount
        item.minSucceededTaskCount = item.minSucceededTaskCount === '' ? null : item.minSucceededTaskCount
        delete item['noChecked']
        return item
      })
      configObj.jobName = this.jobName
      let data = {}
      data.projectId = this.curProject.id
      data.projectName = this.curProject.projectName
      data.config = JSON.stringify(configObj)
      createTask(data).then(res => {
        if (res.message.code === 0) {
          this.reloadChildComponent()
          this.$message({ message: '新建任务成功', showClose: true, type: 'success' })
          this.resetForm()
          this.dialog.createTask = false
        } else if (res.message.code === 40012) {
          this.$message({ message: '运行任务的项目代码不能超过200M,请修改代码后重新运行', showClose: true, type: 'error' })
        } else {
          this.$message({ message: res.message.message, showClose: true, type: 'error' })
        }
      })
    },
    // 创建调试任务 this.curDeubGpuType
    _createDebuggerTask () {
      // 算力计算 判断
      if (Number(this.residualCalculation) < Number(this.debugCalPower)) {
        this.$message({ message: '当前算力不足，请充值', showClose: true, type: 'warning' })
        return false
      }
      this.setRandomJobName()
      this.createJobLoad = this.$loading()
      let curProjectConf = JSON.parse(this.curProject.config)
      this.jupyterConfig.code.projectId = this.curProject.projectName
      this.jupyterConfig.datasets = curProjectConf.datasets
      if (curProjectConf.taskRoles && curProjectConf.taskRoles.length > 0 && curProjectConf.taskRoles[0].image) {
        this.jupyterConfig.taskRoles[0].image = curProjectConf.taskRoles[0].image
      }
      this.jupyterConfig.jobName = this.jobName
      this.jupyterConfig.taskRoles[0].gpuType = this.debuggerGPUType
      this.jupyterConfig.taskRoles[0].memoryMB = this.curDeubGpuType.memory_num * 1024
      this.jupyterConfig.taskRoles[0].shmMB = this.curDeubGpuType.shared_memory_num
      this.jupyterConfig.taskRoles[0].cpuNumber = this.curDeubGpuType.cpu_num
      this.jupyterConfig.taskRoles[0].gpuNumber = this.debuggerGPUNumber
      this.jupyterConfig.taskRoles[0].command = `pip install jupyterlab; service ssh stop; jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir='/code' --port=22 --NotebookApp.tornado_settings='{"headers":{"Content-Security-Policy":"frame-ancestors self http://localhost:9091 https://112.31.12.178:5443 https://forum.bitahub.com; report-uri /api/security/csp-report" }}' --certfile=/jupyterlab/mycert.pem  --keyfile /jupyterlab/mykey.key`
      const data = {}
      data.config = JSON.stringify(this.jupyterConfig)
      data.projectId = this.curProject.id
      data.projectName = this.curProject.projectName
      data.jobType = 2
      data.codeNo = this.newestTaskNo
      // 当 payBy为-99时 个人支付，无需发请求
      if (this.payBy !== -99) {
        this._addTeamTaskRelation(this.jobName, data)
      } else {
        this._createTaskRequest(data)
      }
    },
    _createTaskRequest (data) {
      createTask(data).then(res => {
        this.createJobLoad.close()
        if (res.message.code === 0) {
          this._getJobJupyterUrl()
          // 启动定时器
          if (this.timer === '') {
            this.timer = this._ajaxLoop()
          }
          // 更新子组件
          this.reloadChildComponent()
        } else if (res.message.code === 40012) {
          this.$message({ message: '运行任务的项目代码不能超过200M,请修改代码后重新运行', showClose: true, type: 'error' })
        } else {
          this.$message({ message: res.message.message, showClose: true, type: 'error' })
        }
      })
    },
    // 查询jupyter URL
    _getJobJupyterUrl () {
      let query = `?projectId=${this.$route.query.projectid}`
      getJobJupyterUrl(query).then(res => {
        if (res.message.status === 200) {
          if (res.message.code === 0) {
            this.debuggerState = 2
            this.jupyterUrl = res.data
            if (this.timer !== '') {
              clearInterval(this.timer)
              this.timer = ''
            }
            this.$refs['task-view']._getProjectDetail()
          } else if (res.message.code === -4) {
            this.debuggerState = 1
            // 启动定时器
            if (this.timer === '') {
              this.timer = this._ajaxLoop()
            }
          } else {
            this.debuggerState = 0
            if (this.timer !== '') {
              clearInterval(this.timer)
              this.timer = ''
            }
          }
        } else {
          this.$message({ message: res.message.message, showClose: true, type: 'error' })
        }
      })
    },
    // 获取最近新建的jupyter任务配置
    _getLastJupyterJobConfig () {
      getLastJupyterJobConfig(res => {
        if (res.message.code !== 0) this.$message({ message: res.message.message, showClose: true, type: 'error' })
      })
    },
    // 获取GPU类型
    _getCalculationPowerConfList () {
      const query = `?number=1&token=${this.userInfo.bitaToken}`
      getCalculationPowerConfList(query).then(res => {
        if (res.code === 0) {
          this.gpuTypeOptions = []
          res.result && res.result.forEach(item => {
            if (item.gpu_type === 'debug') {
              this.gpuTypeOptions.push({
                value: item.gpu_type,
                gpu_type: item.gpu_type,
                cpu_num: item.cpu_num,
                memory_num: item.memory_num,
                shared_memory_num: item.shared_memory_num,
                cal_power: item.cal_power
              })
            }
          })
          this.curDeubGpuType = this.gpuTypeOptions[0]
          this.debugCalPower = (this.debuggerGPUNumber * this.curDeubGpuType.cal_power).toFixed(2)
          this.debugConfig = `${this.debuggerGPUNumber}个${this.curDeubGpuType.gpu_type}、${this.debuggerGPUNumber * this.curDeubGpuType.cpu_num}核CPU、${this.debuggerGPUNumber * this.curDeubGpuType.memory_num}G内存、${this.debuggerGPUNumber * this.curDeubGpuType.shared_memory_num}M共享缓存`
          // this.GPUTypeChange(this.GPUType)
          // this.costEstimate()
        }
      })
    },
    // 获取当前用户剩余算力
    _getUserCalculationPower () {
      const query = `?number=1&token=${this.userInfo.bitaToken}`
      getUserCalculationPower(query).then(res => {
        this._getTeamListWithPower()
        if (res.code === 0) this.surplusCalculationPower = res.result.surplusCalculationPower.toFixed(1)
        this.residualCalculation = this.surplusCalculationPower
      })
    },
    // 获取团队列表带算力
    _getTeamListWithPower () {
      getTeamListWithPower().then(res => {
        if (res.message.code === 0) {
          if (res.data && res.data.length > 0) {
            this.payByList.push({
              teamId: -99,
              teamName: '个人',
              power: this.surplusCalculationPower
            })
            this.payByList = [...this.payByList.concat(res.data)]
            this.selectedTeamId = -99
          }
        } else {
          this.$message({ message: res.message.message, showClose: true, type: 'error' })
        }
      })
    },
    // 添加团队任务关系
    _addTeamTaskRelation (taskName, taskData) {
      let data = qs.stringify({
        teamId: this.payBy,
        taskName: taskName,
        cluster: process.env.VUE_APP_CLUSTER,
        token: this.userInfo.bitaToken
      })
      addTeamTaskRelation(data).then(res => {
        if (res.code === 0) {
          this._createTaskRequest(taskData)
        } else {
          this.$message({ message: res.msg, showClose: true, type: 'error' })
        }
      })
    },
    ...mapMutations({
      storeDataSet: 'SET_CUR_DATASET',
      storeProject: 'SET_CUR_PROJECT'
    })
  },
  computed: {
    activeTab: {
      get: function () {
        // 根据路由计算当前激活Tab
        let callback = 0
        this.tabsRoutePath.forEach((v, index) => {
          if (this.$route.path.indexOf(v) === 0) {
            callback = index
          }
        })
        return callback
      }
    },
    ...mapGetters([
      'userInfo'
    ])
  },
  mounted () {
    this._getProjectDetailByProjectId()
    this._getJobJupyterUrl()
    this._getUserCalculationPower()
  },
  beforeDestroy () {
    if (this.timer !== '') clearInterval(this.timer)
  }
}
</script>

<style lang="stylus">
@import "../../common/stylus/detail_page_layer"
.project-detail
  .header-right
    position relative
    top 0
    left 0
    .action-box
      height 30px
      line-height 30px
  .new-task-text
    color #ffffff
  .iconboxs
    position relative
    top 0
    left 0
    padding-left 35px
  .icon-debugger
    position absolute
    top 11px
    left 20px
    background url('../../common/image/spider-icon-blue.png') 0 0 no-repeat
    background-size 12px 12px
    display inline-block
    width 12px
    height 12px
    margin-right 4px
  .icon-debuggerfff
    position absolute
    top 11px
    left 20px
    background url('../../common/image/spider-icon-fff.png') 0 0 no-repeat
    background-size 12px 12px
    display inline-block
    width 12px
    height 12px
    margin-right 4px
  .icon-cfg
    width 16px
    margin-right 9px
    background url('../../common/image/icon/setting.png') 0 0 no-repeat
    background-size contain
  .icon-open
    width 16px
    margin-right 9px
    background url('../../common/image/icon/open.png') 50% 50% no-repeat
    background-size contain
  .icon-task
    background url(../../common/image/icon-project/run-task-no.png) no-repeat center
    background-size 16px 16px
  .icon-code
    background url(../../common/image/icon-project/copy-project-edit-one-no.png) no-repeat center
    background-size 16px 16px
  .icon-data-set
    background url(../../common/image/icon-project/data-set--left-ico-no.png) no-repeat center
    background-size 16px 16px
  .icon-notes
    background url(../../common/image/icon-project/detail-icon-notes-no.png) no-repeat center
    background-size 16px 16px
  .nav-item.active
    .icon-task
      background url(../../common/image/icon-project/run-task.png) no-repeat center
      background-size 16px 16px
    .icon-code
      background url(../../common/image/icon-project/copy-project-edit-one.png) no-repeat center
      background-size 16px 16px
    .icon-data-set
      background url(../../common/image/icon-project/data-set--left-ico.png) no-repeat center
      background-size 16px 16px
    .icon-notes
      background url(../../common/image/icon-project/detail-icon-notes.png) no-repeat center
      background-size 16px 16px
  .el-button--medium
    border 1px solid #2E94F9
    border-radius 3px
    >span
      color #2E94F9
  .header-button
    .button-blue
      background #2E94F9
      span
        color #ffffff
    .el-icon-loading
      color #ffffff
.task-list-main-container
  .form-task-container
    display flex
    width 100%
    .form-task-left
      display inline-block
      width 22%
      height 475px
      background #F8F9FA
      margin-right 3%
      .task-list
        height 80%
        overflow auto
        li
          height 24px
          line-height 24px
          padding 5px 10px
          cursor pointer
          display flex
          justify-content space-between
          color #2D323B
          font-size 14px
          font-weight bold
        .active
          background #E0E3E8
        .nochecked
          color #f56c6c
        .task-del
          display none
        .task-item
          &:hover
            background #E0E3E8
            .task-del
              display inline
      .task-add
        height 20%
        display flex
        align-items center
        justify-content center
        .task-add-btn
          width 100px
          height 30px
          display flex
          align-items center
          justify-content center
          background #e0e3e8
          border-radius 4px
          cursor pointer
    .form-task-right
      width 75%
      float right
      .item-container
        margin-bottom 20px
      .task-right-box
        width 100%
        display flex
        justify-content space-between
        .task-right-item
          width 48%
  .footer-button
    width 100%
    display flex
    align-items center
    justify-content center
    padding 40px 0
  .number-input
    width 100%
  .required:before
    content "*"
    color #f56c6c
    margin-right 4px
  .dialog-footer
    display flex
    justify-content flex-end
  .not-allowed
    cursor not-allowed!important
    color #cbcbcb!important
.open-project-no
  .el-dialog__header
    padding 0
    background pink
    .el-dialog__headerbtn
      top 10px
      right 10px
  .no-wrapper
    min-height 120px
    padding 0 6px
    .title
      padding-bottom 24px
      line-height 18px
      font-size 13px
      color #676767
    .dataset, .model
      display flex
      .tit
        flex 0 0 62px
        line-height 32px
        font-size 14px
        color #676767
      .items
        flex 1
        font-size 0
        .item
          display inline-block
          padding 0 10px
          margin-right 14px
          margin-bottom 16px
          height 32px
          line-height 30px
          border 1px solid #2E94F9
          border-radius 4px
          font-size 14px
          color #2E94F9
          cursor pointer
.debugger-dialog
  .debugger-content
    .title
      margin-right 14px
    .debugger-gpu-select
      width 120px
      margin-right 46px
    .debugger-gpu-number
      width 58px
    .debugger-text
      font-size 13px
      color #9F9F9F
      line-height 18px
      padding 6px 0
      .debugger-text-cal
        color #2E94F9
    .debugger-text-first
      margin-top 20px
    .debugger-tips
      font-size 14px
      color #F44336
      line-height 18px
      padding 10px
      border 1px solid #f44336
      background-color rgba(255, 0, 0, 0.1)
      margin-top 25px
      border-radius 4px
    .cost-payby
      width 100%
      padding-top 30px
      display flex
      .title
        line-height 20px
        font-size 14px
        color #2D323B
      .payby-group
        padding-left 12px
        flex 1
        .payby-group-item
          display block
          margin-left 0
          margin-bottom 17px
          .el-radio__label
            height 20px
            line-height 20px
          .el-radio__label
            padding-left 14px
            color #2D323B
          .payby-group-item-remaining
            margin-left 45px
            font-size 14px
            color #6E6E6E
            line-height 20px
        .payby-group-item:last-child
          margin-bottom 14px
  .debugger-footer-btn
    font-size 14px
    color #2D323B
    padding 6px 20px
    line-height 20px
    border 1px solid #DBDFE6
    border-radius 3px
    background #ffffff
    margin-right 17px
    cursor pointer
    outline none
  .debugger-footer-active
    background #2E94F9
    color #ffffff
    margin 0
  .el-input__inner
    height 32px
    padding 0 0 0 18px!important
    text-align left
  .el-input__icon
    line-height 32px
  .el-input-number__decrease
    right 3px!important
    background #fff
    border none!important
    width auto
  .el-input-number__increase
    right 3px!important
    background #fff
    border none!important
    width auto
  .el-input-number
    line-height 32px
  .el-dialog__body
    padding 13px 50px 43px
  .el-dialog__footer
    display flex
    justify-content center
    padding 0 20px 32px
</style>
